package com.jsh.erp.service.accountItem;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jsh.erp.constants.BusinessConstants;
import com.jsh.erp.constants.ExceptionConstants;
import com.jsh.erp.datasource.entities.*;
import com.jsh.erp.datasource.mappers.*;
import com.jsh.erp.datasource.entities.AccountItem;
import com.jsh.erp.datasource.entities.AccountItemExample;
import com.jsh.erp.datasource.entities.CheckVo;
import com.jsh.erp.datasource.entities.User;
import com.jsh.erp.datasource.vo.AccountItemVo4List;
import com.jsh.erp.exception.BusinessRunTimeException;
import com.jsh.erp.exception.JshException;
import com.jsh.erp.service.depotHead.DepotHeadService;
import com.jsh.erp.service.log.LogService;
import com.jsh.erp.service.systemConfig.SystemConfigService;
import com.jsh.erp.service.user.UserService;
import com.jsh.erp.utils.IdUtils;
import com.jsh.erp.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service
public class AccountItemService {
    private Logger logger = LoggerFactory.getLogger(AccountItemService.class);

    @Resource
    private AccountItemMapper accountItemMapper;
    @Resource
    private AccountItemMapperEx accountItemMapperEx;
    @Resource
    private LogService logService;
    @Resource
    private UserService userService;
    @Resource
    private DepotHeadService depotHeadService;
    @Resource
    private SystemConfigService systemConfigService;
    @Resource
    private AccountHeadMapper accountHeadMapper;
    @Resource
    private DepotHeadMapper depotHeadMapper;
    @Resource
    private AccountHeadMapperEx accountHeadMapperEx;

    public AccountItem getAccountItem(String id)throws Exception {
        AccountItem result=null;
        try{
            result=accountItemMapper.selectByPrimaryKey(id);
        }catch(Exception e){
            JshException.readFail(logger, e, systemConfigService.getLanCode());
        }
        return result;
    }

    public List<AccountItem> getAccountItem()throws Exception {
        AccountItemExample example = new AccountItemExample();
        example.createCriteria().andDeleteFlagNotEqualTo(BusinessConstants.DELETE_FLAG_DELETED);
        List<AccountItem> list=null;
        try{
            list=accountItemMapper.selectByExample(example);
        }catch(Exception e){
            JshException.readFail(logger, e, systemConfigService.getLanCode());
        }
        return list;
    }

    public List<AccountItem> select(String name, Integer type, String remark, int offset, int rows)throws Exception {
        List<AccountItem> list=null;
        try{
            list = accountItemMapperEx.selectByConditionAccountItem(name, type, remark, offset, rows);
        }catch(Exception e){
            JshException.readFail(logger, e, systemConfigService.getLanCode());
        }
        return list;
    }

    public Long countAccountItem(String name, Integer type, String remark)throws Exception {
        Long result=null;
        try{
            result = accountItemMapperEx.countsByAccountItem(name, type, remark);
        }catch(Exception e){
            JshException.readFail(logger, e, systemConfigService.getLanCode());
        }
        return result;
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public int insertAccountItem(JSONObject obj, HttpServletRequest request) throws Exception{
        AccountItem accountItem = JSONObject.parseObject(obj.toJSONString(), AccountItem.class);
        accountItem.setUploadFlag("0");
        int result=0;
        try{
            result = accountItemMapper.insertSelective(accountItem);
            logService.insertLog("财务明细", BusinessConstants.LOG_OPERATION_TYPE_ADD, request);
        }catch(Exception e){
            JshException.writeFail(logger, e, systemConfigService.getLanCode());
        }
        return result;
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public int updateAccountItem(JSONObject obj, HttpServletRequest request)throws Exception {
        AccountItem accountItem = JSONObject.parseObject(obj.toJSONString(), AccountItem.class);
        accountItem.setUploadFlag("0");
        int result=0;
        try{
            result = accountItemMapper.updateByPrimaryKeySelective(accountItem);
            logService.insertLog("财务明细",
                    new StringBuffer(BusinessConstants.LOG_OPERATION_TYPE_EDIT).append(accountItem.getId()).toString(), request);
        }catch(Exception e){
            JshException.writeFail(logger, e, systemConfigService.getLanCode());
        }
        return result;
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public int deleteAccountItem(String id, HttpServletRequest request)throws Exception {
        int result=0;
        AccountItem accountItem =new AccountItem();
        accountItem.setId(id);
        accountItem.setUploadFlag("0");
        accountItem.setDeleteFlag(BusinessConstants.DELETE_FLAG_DELETED);
        try{
            result = accountItemMapper.updateByPrimaryKeySelective(accountItem);
            logService.insertLog("财务明细",
                    new StringBuffer(BusinessConstants.LOG_OPERATION_TYPE_DELETE).append(id).toString(), request);
        }catch(Exception e){
            JshException.writeFail(logger, e, systemConfigService.getLanCode());
        }
        return result;
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public int batchDeleteAccountItem(String ids, HttpServletRequest request)throws Exception {
        List<String> idList = StringUtil.strToStringList(ids);
        AccountItemExample example = new AccountItemExample();
        example.createCriteria().andIdIn(idList);
        AccountItem accountItem =new AccountItem();
        accountItem.setDeleteFlag(BusinessConstants.DELETE_FLAG_DELETED);
        accountItem.setUploadFlag("0");
        int result=0;
        try{
            result = accountItemMapper.updateByExampleSelective(accountItem,example);
            logService.insertLog("财务明细", "批量删除,id集:" + ids, request);
        }catch(Exception e){
            JshException.writeFail(logger, e, systemConfigService.getLanCode());
        }
        return result;
    }

     public int checkIsNameExist(String id, String name) throws Exception{
        AccountItemExample example = new AccountItemExample();
        example.createCriteria().andIdNotEqualTo(id).andDeleteFlagNotEqualTo(BusinessConstants.DELETE_FLAG_DELETED);
        List<AccountItem> list = null;
        try{
            list = accountItemMapper.selectByExample(example);
        }catch(Exception e){
            JshException.readFail(logger, e, systemConfigService.getLanCode());
        }
        return list==null?0:list.size();
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public int insertAccountItemWithObj(AccountItem accountItem)throws Exception {
        accountItem.setUploadFlag("0");
        int result=0;
        try{
            result = accountItemMapper.insertSelective(accountItem);
        }catch(Exception e){
            JshException.writeFail(logger, e, systemConfigService.getLanCode());
        }
        return result;
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public int updateAccountItemWithObj(AccountItem accountItem)throws Exception {
        accountItem.setUploadFlag("0");
        int result=0;
        try{
            result = accountItemMapper.updateByPrimaryKeySelective(accountItem);
        }catch(Exception e){
            JshException.writeFail(logger, e, systemConfigService.getLanCode());
        }
        return result;
    }

    public List<AccountItemVo4List> getDetailList(String headerId) {
        List<AccountItemVo4List> list=null;
        try{
            list = accountItemMapperEx.getDetailList(headerId);
        }catch(Exception e){
            JshException.readFail(logger, e, systemConfigService.getLanCode());
        }
        return list;
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public void saveDetials(String rows, String headerId, String type, HttpServletRequest request,String actionType) throws Exception {
        //查询单据主表信息
        AccountHead accountHead = accountHeadMapper.selectByPrimaryKey(headerId);
        //删除单据的明细
        batchDeleteAccountItemByHeadIds(headerId);
        JSONArray rowArr = JSONArray.parseArray(rows);
        if (null != rowArr && rowArr.size()>0) {
            for (int i = 0; i < rowArr.size(); i++) {
                AccountItem accountItem = new AccountItem();
                accountItem.setId(IdUtils.getUUID());
                JSONObject tempInsertedJson = JSONObject.parseObject(rowArr.getString(i));
                accountItem.setHeaderId(headerId);
                if (tempInsertedJson.get("accountId") != null && !tempInsertedJson.get("accountId").equals("")) {
                    accountItem.setAccountId(tempInsertedJson.getString("accountId"));
                }
                if (tempInsertedJson.get("inOutItemId") != null && !tempInsertedJson.get("inOutItemId").equals("")) {
                    accountItem.setInOutItemId(tempInsertedJson.getString("inOutItemId"));
                }
                if (tempInsertedJson.get("billNumber") != null && !tempInsertedJson.get("billNumber").equals("")) {
                    String billNo = tempInsertedJson.getString("billNumber");
                    DepotHead depotHead = depotHeadService.getDepotHead(billNo);
                    accountItem.setBillId(depotHead.getId());
                    //给结算的单据修改状态
                    if ("收款".equals(type) || "直发收款".equals(type) || "付款".equals(type) || "直发付款".equals(type)) {
                        BigDecimal eachAmount = tempInsertedJson.getBigDecimal("eachAmount").abs();
                        BigDecimal realFinishAmount= BigDecimal.ZERO;
                        if ("add".equals(actionType)) {
                            realFinishAmount = accountHeadMapperEx.getEachAmount(null,depotHead.getId());
                        } else if ("update".equals(actionType)) {
                            realFinishAmount = accountHeadMapperEx.getEachAmount(accountHead.getId(),depotHead.getId());
                        }
                        BigDecimal discountLastMoney = depotHead.getDiscountLastMoney();
                        int custom12 = eachAmount.add(realFinishAmount).compareTo(discountLastMoney);
                        if (custom12 > 0) {
                            throw new BusinessRunTimeException(ExceptionConstants.ACCOUNT_HEAD_EACH_AMOUNT_FAILED_CODE,
                                    "zh".equals(systemConfigService.getLanCode()) ? ExceptionConstants.ACCOUNT_HEAD_EACH_AMOUNT_FAILED_MSG : ExceptionConstants.ACCOUNT_HEAD_EACH_AMOUNT_FAILED_MSG_US);
                        }else if (custom12==0){
                            depotHead.setCustom12(1);
                        }else {
                            depotHead.setCustom12(2);
                        }
                        depotHead.setCustom9(eachAmount);
                        depotHeadMapper.updateByPrimaryKeySelective(depotHead);
                    }
                }
                if (tempInsertedJson.get("needDebt") != null && !tempInsertedJson.get("needDebt").equals("")) {
                    accountItem.setNeedDebt(tempInsertedJson.getBigDecimal("needDebt"));
                }
                if (tempInsertedJson.get("finishDebt") != null && !tempInsertedJson.get("finishDebt").equals("")) {
                    accountItem.setFinishDebt(tempInsertedJson.getBigDecimal("finishDebt"));
                }
                if (tempInsertedJson.get("exchangeTime") != null && !tempInsertedJson.get("exchangeTime").equals("")) {
                    accountItem.setExchangeTime(tempInsertedJson.getDate("exchangeTime"));
                }
                if (tempInsertedJson.get("checkCode") != null && !tempInsertedJson.get("checkCode").equals("")) {
                    accountItem.setCheckCode(tempInsertedJson.getString("checkCode"));
                }
                if (tempInsertedJson.get("isExchange") != null && !tempInsertedJson.get("isExchange").equals("")) {
                    accountItem.setIsExchange(tempInsertedJson.getString("isExchange"));
                }
                if (tempInsertedJson.get("custom1") != null && !tempInsertedJson.get("custom1").equals("")) {
                    accountItem.setCustom1(tempInsertedJson.getString("custom1"));
                }
                if (tempInsertedJson.get("custom2") != null && !tempInsertedJson.get("custom2").equals("")) {
                    accountItem.setCustom2(tempInsertedJson.getString("custom2"));
                }
                if (tempInsertedJson.get("custom3") != null && !tempInsertedJson.get("custom3").equals("")) {
                    accountItem.setCustom3(tempInsertedJson.getString("custom3"));
                }
                if (tempInsertedJson.get("custom4") != null && !tempInsertedJson.get("custom4").equals("")) {
                    accountItem.setCustom4(tempInsertedJson.getString("custom4"));
                }
                if (tempInsertedJson.get("custom5") != null && !tempInsertedJson.get("custom5").equals("")) {
                    accountItem.setCustom5(tempInsertedJson.getString("custom5"));
                }
                if (tempInsertedJson.get("custom6") != null && !tempInsertedJson.get("custom6").equals("")) {
                    accountItem.setCustom6(tempInsertedJson.getBigDecimal("custom6"));
                }
                if (tempInsertedJson.get("custom7") != null && !tempInsertedJson.get("custom7").equals("")) {
                    accountItem.setCustom7(tempInsertedJson.getBigDecimal("custom7"));
                }
                if (tempInsertedJson.get("custom8") != null && !tempInsertedJson.get("custom8").equals("")) {
                    accountItem.setCustom8(tempInsertedJson.getBigDecimal("custom8"));
                }
                if (tempInsertedJson.get("custom9") != null && !tempInsertedJson.get("custom9").equals("")) {
                    accountItem.setCustom9(tempInsertedJson.getBigDecimal("custom9"));
                }
                if (tempInsertedJson.get("custom10") != null && !tempInsertedJson.get("custom10").equals("")) {
                    accountItem.setCustom10(tempInsertedJson.getBigDecimal("custom10"));
                }
                if (tempInsertedJson.get("custom11") != null && !tempInsertedJson.get("custom11").equals("")) {
                    accountItem.setCustom11(tempInsertedJson.getInteger("custom11"));
                }
                if (tempInsertedJson.get("custom12") != null && !tempInsertedJson.get("custom12").equals("")) {
                    accountItem.setCustom12(tempInsertedJson.getInteger("custom12"));
                }
                if (tempInsertedJson.get("custom13") != null && !tempInsertedJson.get("custom13").equals("")) {
                    accountItem.setCustom13(tempInsertedJson.getInteger("custom13"));
                }
                if (tempInsertedJson.get("custom14") != null && !tempInsertedJson.get("custom14").equals("")) {
                    accountItem.setCustom14(tempInsertedJson.getInteger("custom14"));
                }
                if (tempInsertedJson.get("custom15") != null && !tempInsertedJson.get("custom15").equals("")) {
                    accountItem.setCustom15(tempInsertedJson.getInteger("custom15"));
                }
                if (tempInsertedJson.get("transpotNo") != null && !tempInsertedJson.get("transpotNo").equals("")) {
                    accountItem.setTranspotNo(tempInsertedJson.getString("transpotNo"));
                }
                if (tempInsertedJson.get("transpotName") != null && !tempInsertedJson.get("transpotName").equals("")) {
                    accountItem.setTranspotName(tempInsertedJson.getString("transpotName"));
                }
                if (tempInsertedJson.get("packSize") != null && !tempInsertedJson.get("packSize").equals("")) {
                    accountItem.setPackSize(tempInsertedJson.getString("packSize"));
                }
                if (tempInsertedJson.get("gtin") != null && !tempInsertedJson.get("gtin").equals("")) {
                    accountItem.setGtin(tempInsertedJson.getString("gtin"));
                }
                if (tempInsertedJson.get("uom") != null && !tempInsertedJson.get("uom").equals("")) {
                    accountItem.setUom(tempInsertedJson.getString("uom"));
                }
                if (tempInsertedJson.get("packsOrdered") != null && !tempInsertedJson.get("packsOrdered").equals("")) {
                    accountItem.setPacksOrdered(tempInsertedJson.getBigDecimal("packsOrdered"));
                }
                if (tempInsertedJson.get("packsSupplied") != null && !tempInsertedJson.get("packsSupplied").equals("")) {
                    accountItem.setPacksSupplied(tempInsertedJson.getBigDecimal("packsSupplied"));
                }
                if (tempInsertedJson.get("unitPrice") != null && !tempInsertedJson.get("unitPrice").equals("")) {
                    accountItem.setUnitPrice(tempInsertedJson.getBigDecimal("unitPrice"));
                }
                if (tempInsertedJson.get("amount") != null && !tempInsertedJson.get("amount").equals("")) {
                    accountItem.setAmount(tempInsertedJson.getBigDecimal("amount"));
                }
                if (tempInsertedJson.get("discountAmount") != null && !tempInsertedJson.get("discountAmount").equals("")) {
                    accountItem.setDiscountAmount(tempInsertedJson.getBigDecimal("discountAmount"));
                }
                if (tempInsertedJson.get("paymentType") != null && !tempInsertedJson.get("paymentType").equals("")) {
                    accountItem.setPaymentType(tempInsertedJson.getString("paymentType"));
                }
                if (tempInsertedJson.get("receiveTime") != null && !tempInsertedJson.get("receiveTime").equals("")) {
                    accountItem.setReceiveTime(tempInsertedJson.getDate("receiveTime"));
                }
                if (tempInsertedJson.get("depotId") != null && !tempInsertedJson.get("depotId").equals("")) {
                    accountItem.setDepotId(tempInsertedJson.getString("depotId"));
                }
                if (tempInsertedJson.get("invoiceNo") != null && !tempInsertedJson.get("invoiceNo").equals("")) {
                    accountItem.setInvoiceNo(tempInsertedJson.getString("invoiceNo"));
                }
                //如果数量+已完成数量>原订单数量，给出预警(判断前提是存在关联订单)
                if ("预付款单".equals(type) || "直发预付款".equals(type) || "直发预收款".equals(type) || "预收款单".equals(type)) {
                    //获取关联订单的金额
                    BigDecimal discountLastMoney = depotHeadService.getDepotHead(accountHead.getNumber()).getDiscountLastMoney();
                    BigDecimal eachAmount = tempInsertedJson.getBigDecimal("eachAmount").abs();
                    if ("add".equals(actionType)) {
                        //除去此单据之外的预收/预付
                        BigDecimal realFinishAmount = accountHeadMapperEx.getRealAmount(type, accountHead.getNumber(),null,accountHead.getBillNo());
                        if (eachAmount.add(realFinishAmount).compareTo(discountLastMoney) > 0) {
                            throw new BusinessRunTimeException(ExceptionConstants.ACCOUNT_HEAD_CHANGE_AMOUNT_FAILED_CODE,
                                    String.format("zh".equals(systemConfigService.getLanCode()) ? ExceptionConstants.ACCOUNT_HEAD_CHANGE_AMOUNT_FAILED_MSG : ExceptionConstants.ACCOUNT_HEAD_CHANGE_AMOUNT_FAILED_MSG_US));
                        }
                    } else if ("update".equals(actionType)) {
                        //除去此单据之外的预收/预付
                        BigDecimal realFinishAmount = accountHeadMapperEx.getRealAmount(type, accountHead.getNumber(),accountHead.getId(),accountHead.getBillNo());
                        if (eachAmount.add(realFinishAmount).compareTo(discountLastMoney) > 0) {
                            throw new BusinessRunTimeException(ExceptionConstants.ACCOUNT_HEAD_CHANGE_AMOUNT_FAILED_CODE,
                                    String.format("zh".equals(systemConfigService.getLanCode()) ? ExceptionConstants.ACCOUNT_HEAD_CHANGE_AMOUNT_FAILED_MSG : ExceptionConstants.ACCOUNT_HEAD_CHANGE_AMOUNT_FAILED_MSG_US));
                        }
                    }
                }
                if (tempInsertedJson.get("eachAmount") != null && !tempInsertedJson.get("eachAmount").equals("")) {
                    BigDecimal eachAmount = tempInsertedJson.getBigDecimal("eachAmount");
                    if (type.equals("付款")||type.equals("运输付款")||type.equals("直发付款")
                            ||type.equals("直发运输付款")||type.equals("支票核销")||type.equals("直发预付款")
                            ||type.equals("预付款单")) {
                        eachAmount = BigDecimal.ZERO.subtract(eachAmount);
                    }
                    accountItem.setEachAmount(eachAmount);
                } else {
                    accountItem.setEachAmount(BigDecimal.ZERO);
                }

                accountItem.setRemark(tempInsertedJson.getString("remark"));
                this.insertAccountItemWithObj(accountItem);
                if ("运费".equals(accountHead.getType())){
                    DepotHead depotHead = depotHeadService.getDepotHead(accountHead.getNumber());
                    depotHead.setFreightStatus("1");
                    depotHead.setUploadFlag("0");
                    depotHeadMapper.updateByPrimaryKeySelective(depotHead);

                    DepotHead purchaseDepotHead = depotHeadService.getDepotHead(accountHead.getCustom1());
                    purchaseDepotHead.setFreightStatus("1");
                    purchaseDepotHead.setUploadFlag("0");
                    depotHeadMapper.updateByPrimaryKeySelective(purchaseDepotHead);

                }
                if (StringUtil.isNotEmpty(accountItem.getCustom1()) && ("运输付款".equals(accountHead.getType()) || "直发运输付款".equals(accountHead.getType()))) {
                    //运费单明细
                    AccountItem accountItem1 = accountItemMapper.selectByPrimaryKey(accountItem.getCustom1());
                    accountItem1.setIsExchange("1");
                    accountItem1.setUploadFlag("0");
                    accountItemMapper.updateByPrimaryKeySelective(accountItem1);
                }
            }
        } else {
            throw new BusinessRunTimeException(ExceptionConstants.ACCOUNT_HEAD_ROW_FAILED_CODE,
                    String.format( "zh".equals(systemConfigService.getLanCode()) ? ExceptionConstants.ACCOUNT_HEAD_ROW_FAILED_MSG : ExceptionConstants.ACCOUNT_HEAD_ROW_FAILED_MSG_US ));
        }
    }
    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public void deleteAccountItemHeadId(String headerId)throws Exception {
        AccountItemExample example = new AccountItemExample();
        example.createCriteria().andHeaderIdEqualTo(headerId);
        try{
            accountItemMapper.deleteByExample(example);
        }catch(Exception e){
            JshException.writeFail(logger, e, systemConfigService.getLanCode());
        }
    }
    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public void batchDeleteAccountItemByHeadIds(String headerId)throws Exception {
        User userInfo=userService.getCurrentUser();
        String [] idArray=headerId.split(",");
        try{
            accountItemMapperEx.batchDeleteAccountItemByHeadIds(new Date(),userInfo==null?null:userInfo.getId(),idArray);
        }catch(Exception e){
            JshException.writeFail(logger, e, systemConfigService.getLanCode());
        }
    }

    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public int batchDeleteAccountItemByIds(String ids) throws Exception{
        logService.insertLog("财务明细",
                new StringBuffer(BusinessConstants.LOG_OPERATION_TYPE_DELETE).append(ids).toString(),
                StringUtil.getRequest());
        User userInfo=userService.getCurrentUser();
        String [] idArray=ids.split(",");
        int result=0;
        try{
            result = accountItemMapperEx.batchDeleteAccountItemByIds(new Date(),userInfo==null?null:userInfo.getId(),idArray);
        }catch(Exception e){
            JshException.writeFail(logger, e, systemConfigService.getLanCode());
        }
        return result;
    }

    public BigDecimal getEachAmountByBillId(String billId) {
        return accountItemMapperEx.getEachAmountByBillId(billId).abs();
    }

    public List<CheckVo> checkList(String organId) {
        return accountItemMapperEx.checkList(organId);
    }
}
